package com.yue.springDemo.framework.expection;

import com.yue.springDemo.business.bean.ResponseResult;
import com.yue.springDemo.commons.logger.MyLoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 统一的异常处理
 */
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class Exception2Controller extends AbstractErrorController {

    private MyLoggerFactory logger;

    private ErrorProperties errorProperties;

    @Autowired
    public Exception2Controller(ErrorAttributes errorAttributes, ServerProperties serverProperties, MyLoggerFactory logger) {
        super(errorAttributes);
        this.errorProperties = serverProperties.getError();
        this.logger = logger;
    }

    @Override
    public String getErrorPath() {
        return errorProperties.getPath();
    }

    /**
     * 401、403、404异常处理
     *
     * @param request 请求
     * @return 返回
     */
    @RequestMapping
    @ResponseBody
    public ResponseResult error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        String path = String.valueOf(body.get("path"));

        StringBuilder errorMessage = new StringBuilder();
        HttpStatus status = getStatus(request);
        if (HttpStatus.BAD_REQUEST.equals(status)) {
            errorMessage.append(path).append(" ").append("该接口不存在");
        } else if (HttpStatus.UNAUTHORIZED.equals(status)) {
            errorMessage.append(path).append(" ").append("未登录");
        } else if (HttpStatus.FORBIDDEN.equals(status)) {
            errorMessage.append(path).append(" ").append("无权限访问该接口");
        } else {
            String message = String.valueOf(body.get("message"));
            errorMessage.append(status.value()).append("：").append(path).append(" ").append(message);
        }
        logger.error(errorMessage.toString());
        return ResponseResult.error(String.valueOf(status.value()), errorMessage.toString());
    }

    /**
     * 获取网络状态
     *
     * @param request 请求
     * @return 状态
     */
    protected HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        try {
            return HttpStatus.valueOf(statusCode);
        } catch (Exception ex) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }

    /**
     * 是否堆栈跟踪
     *
     * @param request  请求
     * @param produces 类型
     * @return 返回
     */
    private boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
        ErrorProperties.IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
        if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
            return true;
        }
        if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
            return getTraceParameter(request);
        }
        return false;
    }

    /**
     * 异常配置
     *
     * @return 配置
     */
    private ErrorProperties getErrorProperties() {
        return this.errorProperties;
    }

}

